<template>
  <div>
    <div>管道漫游案例</div>
    <div ref="webgl"></div>
  </div>
</template>
<script lang="ts" setup>
  import * as THREE from 'three';
  import { OrbitControls } from 'three/addons';
  import { onMounted, ref } from 'vue';

  const webgl: any = ref(null);
  let scene: any = null;
  let camera: any = null;
  let render: any = null;
  let controls;
  let i = 1;
  let pointsArr: THREE.Vector3[] = [];
  onMounted(() => {
    init();
  });
  function init() {
    scene = new THREE.Scene();
    // 正投影相机
    const width = window.innerWidth; //canvas画布宽度
    const height = window.innerHeight; //canvas画布高度

    camera = new THREE.PerspectiveCamera(90, width / height, 1, 1000);
    camera.position.set(300, 300, 300);
    camera.lookAt(scene.position);
    render = new THREE.WebGLRenderer();
    // 背景颜色
    render.setClearColor('#f1f2f6');
    render.setSize(width, height);
    webgl.value.appendChild(render.domElement);
    controls = new OrbitControls(camera, render.domElement);
    const amLight = new THREE.AmbientLight(0xffffff);
    scene.add(amLight);
    const helper = new THREE.AxesHelper(200);
    scene.add(helper);
    const pointLight = new THREE.PointLight(0xffffff);
    pointLight.position.set(100, 100, 100);
    scene.add(pointLight);
    const pointLightHelper = new THREE.PointLightHelper(pointLight);
    scene.add(pointLightHelper);

    // 三维样条曲线
    const path = new THREE.CatmullRomCurve3([
      new THREE.Vector3(-50, 20, 90),
      new THREE.Vector3(-10, 40, 40),
      new THREE.Vector3(0, 0, 0),
      new THREE.Vector3(60, -60, 0),
      new THREE.Vector3(90, -40, 60),
      new THREE.Vector3(120, 30, 30),
    ]);
    // const shape = new THREE.Shape([
    //   // 按照特定顺序，依次书写多边形顶点坐标
    //   new THREE.Vector2(0, 0), //多边形起点
    //   new THREE.Vector2(0, 10),
    //   new THREE.Vector2(10, 10),
    //   new THREE.Vector2(10, 0),
    // ]);
    // 样条曲线path作为TubeGeometry参数生成管道
    const geometry = new THREE.TubeGeometry(path, 200, 5, 30);
    // const geometry = new THREE.ExtrudeGeometry(shape, {
    //   extrudePath: path,
    //   steps: 100, //沿着路径细分精度，越大越光滑
    // });
    const texLoader = new THREE.TextureLoader();
    //纹理贴图
    const texture = texLoader.load('../../../../public/38.png');
    //UV坐标U方向阵列模式
    texture.wrapS = THREE.RepeatWrapping;
    //纹理沿着管道方向阵列(UV坐标U方向)
    texture.repeat.x = 10;
    const material = new THREE.MeshLambertMaterial({
      map: texture,
      side: THREE.DoubleSide, //双面显示看到管道内壁
    });
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
    // 从曲线上等间距获取一定数量点坐标
    pointsArr = path.getSpacedPoints(500);
    console.log('pointsArr', pointsArr);

    renderFun();
  }

  function renderFun() {
    // 渲染循环
    if (i < pointsArr.length - 1) {
      // 相机位置设置在当前点位置
      camera.position.copy(pointsArr[i]);
      // 曲线上当前点pointsArr[i]和下一个点pointsArr[i+1]近似模拟当前点曲线切线
      // 设置相机观察点为当前点的下一个点，相机视线和当前点曲线切线重合
      camera.lookAt(pointsArr[i + 1]);
      controls.target.copy(pointsArr[i + 1]);

      i += 1; //调节速度
    } else {
      i = 0;
    }

    controls.update();
    // controls.update(); //update()函数内会执行camera.lookAt(controls.target)
    render.render(scene, camera);
    requestAnimationFrame(renderFun);
  }
</script>
<style lang=""></style>
